import { BleManager, Device } from 'react-native-ble-plx';

interface GameMessage {
  type: 'faction' | 'move' | 'resource';
  payload: any;
}

class BluetoothConnector {
  private manager: BleManager;
  private connectedDevices: Device[] = [];
  private messageHandlers: ((msg: GameMessage) => void)[] = [];

  constructor() {
    this.manager = new BleManager();
  }

  async scanDevices(onDeviceFound: (device: Device) => void) {
    try {
      const subscription = this.manager.onStateChange((state) => {
        if (state === 'PoweredOn') {
          this.manager.startDeviceScan(null, null, (error, device) => {
            if (error) {
              console.error('Scan error:', error);
              return;
            }
            if (device.name?.includes('Yongle')) {
              onDeviceFound(device);
            }
          });
          subscription.remove();
        }
      }, true);
    } catch (error) {
      console.error('Bluetooth scan failed:', error);
    }
  }

  private retryAttempts = 0;
  private maxRetries = 3;

  async connectToDevice(deviceId: string): Promise<Device> {
    let lastError: any = null;
    
    for (let i = 0; i < this.maxRetries; i++) {
      try {
        const device = await this.manager.connectToDevice(deviceId, {
          autoConnect: false,
          requestMTU: 128
        });
        
        await device.discoverAllServicesAndCharacteristics();
        this.connectedDevices.push(device);
        this.retryAttempts = 0;
        
        // Setup connection monitoring
        device.onDisconnected((error, device) => {
          console.log('Device disconnected:', device?.id);
          this.handleDisconnection(deviceId);
        });
        
        console.log('Successfully connected to:', device.name);
        this.setupNotification(device);
        return device;
      } catch (error) {
        lastError = error;
        console.warn(`Connection attempt ${i + 1} failed:`, error);
        await new Promise(resolve => setTimeout(resolve, 1000 * (i + 1)));
      }
    }
    
    console.error(`Failed to connect after ${this.maxRetries} attempts`);
    throw lastError;
  }

  private handleDisconnection(deviceId: string) {
    this.connectedDevices = this.connectedDevices.filter(d => d.id !== deviceId);
    if (this.retryAttempts < this.maxRetries) {
      this.retryAttempts++;
      console.log(`Attempting to reconnect (${this.retryAttempts}/${this.maxRetries})`);
      setTimeout(() => this.connectToDevice(deviceId), 2000);
    }
  }

  private setupNotification(device: Device) {
    device.monitorCharacteristicForService(
      '0000FFE0-0000-1000-8000-00805F9B34FB',
      '0000FFE1-0000-1000-8000-00805F9B34FB',
      (error, characteristic) => {
        if (error || !characteristic?.value) {
          console.error('Notification error:', error);
          return;
        }
        this.handleMessage(characteristic.value);
      }
    );
  }

  private handleMessage(data: string) {
    try {
      if (!data || typeof data !== 'string') {
        throw new Error('Invalid message data');
      }
      
      const message = JSON.parse(data) as GameMessage;
      
      if (!message.type || !message.payload) {
        throw new Error('Invalid message format');
      }

      // 验证消息类型
      const validTypes = ['game_state', 'battle_action', 'player_action'];
      if (!validTypes.includes(message.type)) {
        throw new Error(`Unknown message type: ${message.type}`);
      }

      // 处理战斗动作
      if (message.type === 'battle_action') {
        const { attacker, target, damage, targetDestroyed } = message.payload;
        
        if (!attacker || !target || typeof damage !== 'number' || typeof targetDestroyed !== 'boolean') {
          throw new Error('Invalid battle action payload');
        }
        
        this.messageHandlers.forEach(handler => handler({
          type: 'battle_result',
          payload: { attacker, target, damage, targetDestroyed }
        }));
      } else {
        this.messageHandlers.forEach(handler => handler(message));
      }
    } catch (error) {
      console.error('Message processing failed:', error);
      // 可以添加错误上报或恢复逻辑
    }
  }

  async broadcastMessage(message: GameMessage) {
    const data = JSON.stringify({
      ...message,
      timestamp: Date.now(),
      version: '1.0'
    });
    await Promise.all(this.connectedDevices.map(async (device) => {
      try {
        await device.writeCharacteristicWithResponseForService(
          '0000FFE0-0000-1000-8000-00805F9B34FB',
          '0000FFE1-0000-1000-8000-00805F9B34FB',
          data
        );
      } catch (error) {
        console.error('Broadcast error:', error);
      }
    }));
  }

  async syncGameState(state: any) {
    await this.broadcastMessage({
      type: 'game_state',
      payload: state
    });
  }

  async sendAction(action: string, payload: any) {
    await this.broadcastMessage({
      type: 'player_action',
      payload: {
        action,
        ...payload
      }
    });
  }

  addMessageHandler(handler: (msg: GameMessage) => void) {
    this.messageHandlers.push(handler);
    return () => {
      this.messageHandlers = this.messageHandlers.filter(h => h !== handler);
    };
  }

  async disconnectAll() {
    await Promise.all(this.connectedDevices.map(device => 
      this.manager.cancelDeviceConnection(device.id)
    ));
    this.connectedDevices = [];
  }
}

export default new BluetoothConnector();
